package Products;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import junit.framework.TestCase;

import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;

import Exceptions.HistoricalInformationException;
import Exceptions.ProductNeverPurchasedException;
import Exceptions.ProductSalesPriceNeverSetException;
import Magnitudes.Kilogram;
import Magnitudes.Pesos;
import Magnitudes.Money;

public class PresentationTest extends TestCase {

	Presentation presentationToTest;
	Kilogram kiloMock = mock(Kilogram.class);
	Exception exception;
	Pesos tenPesos = mock(Pesos.class);
	DateTime today = DateTime.now();
	DateTime yesterday = today.minusDays(1);
	
	
	@Before
	public void setUp(){
		presentationToTest = new Presentation(kiloMock, "123456");
		when(kiloMock.toString()).thenReturn("5.0Kg");
		when(tenPesos.amount()).thenReturn((double) 10);
	}
	

	@Test
	public void testGivenPresentationToTestWhenAskedForGetBarcodeShouldReturnTheBarcode(){
		String returnValue = presentationToTest.getBarcode();
		assertEquals("123456", returnValue);
	}
	
	
	@Test
	public void testGivenPresentationToTestWhenAskedForPrintPresentationShouldReturnThePresentationToString(){
		String returnValue = presentationToTest.printPresentationMagnitude();
		assertEquals(kiloMock.toString(), returnValue);
	}
	
	
	@Test//(expected = ProductNeverPurchasedException.class)
	public void testGivenPresentationToTestWhenAskedForGetUnitPurchasePriceShouldRaiseProductNeverPurchasedException(){
				
		try {
			@SuppressWarnings("unused")
			Money price = presentationToTest.getUnitPurchasePrice();
			fail();
		} catch (ProductNeverPurchasedException productNeverPurchasedException){ 
		}
	}
	
	
	@Test
	public void testGivenPresentationWithPurchasePriceAskedForGetUnitPurchasePriceShouldReturnThatPrice(){
		presentationToTest.updateUnitPurchasePriceTo(tenPesos);
		Money returnValue = null;
		try {
			returnValue = presentationToTest.getUnitPurchasePrice();
		} catch (ProductNeverPurchasedException e) {
			e.printStackTrace();
		}
		assertTrue(returnValue.equals(tenPesos));
		
	}
	
	
	@Test
	public void testGivenPresentationWithPurchasePriceAskedForGetUnitSalesPriceShouldRaiseProductSalesPriceNeverSetException(){
		
		presentationToTest.updateUnitPurchasePriceTo(tenPesos);
		
		try {
			Money price = presentationToTest.getUnitSalesPrice();
		} catch (ProductSalesPriceNeverSetException productSalesPriceNeverSetException){
			exception = productSalesPriceNeverSetException;
		}		
		assertNotNull(exception);
		assertTrue(exception.getMessage().contains("The product sales price was never set. Sales price unknown."));
	}
		
	
	@Test
	public void testGivenPresentationToTestWhenAskedForGetUnitSalesPriceShouldRaiseProductSalesPriceNeverSetException(){
				
		try {
			@SuppressWarnings("unused")
			Money price = presentationToTest.getUnitSalesPrice();
		} catch (ProductSalesPriceNeverSetException productSalesPriceNeverSetException){
			exception = productSalesPriceNeverSetException;
		}		
		assertNotNull(exception);
		assertTrue(exception.getMessage().contains("The product sales price was never set. Sales price unknown."));
	}
	
	
	@Test
	public void testGivenPresentationWithSalesPriceAskedForGetUnitSalesPriceShouldReturnThatPrice(){
		presentationToTest.updateUnitPurchasePriceTo(tenPesos);
		presentationToTest.updateUnitSalesPriceTo(tenPesos);
		Money returnValue = null;
		try {
			returnValue = presentationToTest.getUnitPurchasePrice();
		} catch (ProductNeverPurchasedException e) {
			e.printStackTrace();
		}
		assertTrue(tenPesos.equals(returnValue));
	}
	
	@Test
	public void testGivenAPresentationWithoutTodaysSalesPriceWhenAskedForTodaysPriceShouldRaiseHistoricalInformationException(){
		
		try {
			presentationToTest.salesPriceAt(today);
		} catch (HistoricalInformationException historicalInformationException) {
			exception = historicalInformationException;
		}		
		assertNotNull(exception);
		assertTrue(exception.getMessage().contains("Historical information not available"));		
	}
	
	
	@Test
	public void testGivenAPresentationWithTodaysSalesPriceWhenAskedForTodaysPriceShouldReturnTheGivenOne(){
		
		presentationToTest.updateUnitSalesPriceTo(tenPesos);
		try {
			assertEquals(tenPesos, presentationToTest.salesPriceAt(today));
		} catch (HistoricalInformationException e) {			
			e.printStackTrace();
		}		
	}
	
	
	@Test
	public void testGivenAPresentationWithoutTodaysPurchasePriceWhenAskedForTodaysPriceShouldRaiseHistoricalInformationException(){
		
		try {
			presentationToTest.purchasePriceAt(today);
		} catch (HistoricalInformationException historicalInformationException) {
			exception = historicalInformationException;
		}		
		assertNotNull(exception);
		assertTrue(exception.getMessage().contains("Historical information not available"));		
	}
	
	
	@Test
	public void testGivenAPresentationWithTodaysPurchasePriceWhenAskedForTodaysPriceShouldReturnTheGivenOne(){
		presentationToTest.updateUnitPurchasePriceTo(tenPesos);
		Money returnValue = null;
		try {
			returnValue = presentationToTest.purchasePriceAt(today);
		} catch (HistoricalInformationException e) {
			e.printStackTrace();
		}
		//assertNotNull(returnValue);
		assertTrue(tenPesos.equals(returnValue));		
	}
	
	
	
}
